from machine.config import Config
import os

import asyncio.subprocess


async def get_process(program_under_test: str, *args) -> asyncio.subprocess.Process:
    return await asyncio.create_subprocess_exec(program_under_test, *args, stdout=asyncio.subprocess.PIPE,
                                                stdin=asyncio.subprocess.PIPE)


async def read_line(stream: asyncio.StreamReader, timeout: float) -> str:
    try:
        return await asyncio.wait_for(stream.readline(), timeout=timeout)
    except asyncio.TimeoutError:
        return ""


async def read_lines(stream: asyncio.StreamReader, timeout: float) -> list[str]:
    lines = []
    try:

        while True:
            line = await asyncio.wait_for(stream.readline(), timeout=timeout)
            if not line:
                break
            else:
                lines.append(line)
        return lines
    except asyncio.TimeoutError:
        return lines


def write_line(stream: asyncio.StreamWriter, data: bytes) -> bytes:
    try:
        stream.write(data)
    except asyncio.TimeoutError:
        return b''


async def write_and_read_lines(input_str: str) -> str:
    cfg = Config()
    os.chdir(cfg.work_directory)

    print(f"Checking for the executable file '{cfg.program_under_test}'")
    isExist = os.path.exists(cfg.program_under_test)
    assert isExist == True, "It was expected that CMake builds the executable file. Make sure that the executable file is correctly assembled using CMake."

    process = await get_process(cfg.program_under_test, *cfg.program_args)
    write_line(process.stdin, input_str.encode("utf-8"))
    byte_lines = await read_lines(process.stdout, cfg.action_timeout)
    decoded_lines = [
        x.decode(encoding='UTF-8', errors='backslashreplace') for x in byte_lines]
    output_str = "".join(decoded_lines)
    return output_str
